import mongoose from 'mongoose';
import { logger } from '../utils/logger';
import config from './env';

/**
 * 数据库连接监控类
 */
class DatabaseMonitor {
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;
  private reconnectInterval = 5000; // 5秒

  /**
   * 连接数据库
   */
  async connect(): Promise<void> {
    try {
      await mongoose.connect(config.MONGODB_URI);
      this.reconnectAttempts = 0;
      logger.info(`MongoDB 连接成功: ${config.MONGODB_URI}`);
      this.setupEventListeners();
    } catch (error) {
      logger.error('MongoDB 初始连接失败:', error);
      await this.handleReconnection();
    }
  }

  /**
   * 设置数据库事件监听器
   */
  private setupEventListeners(): void {
    const db = mongoose.connection;

    // 连接成功
    db.on('connected', () => {
      logger.info('MongoDB 连接已建立');
    });

    // 连接断开
    db.on('disconnected', () => {
      logger.warn('MongoDB 连接已断开');
    });

    // 连接错误
    db.on('error', (error) => {
      logger.error('MongoDB 连接错误:', error);
    });

    // 重新连接
    db.on('reconnected', () => {
      logger.info('MongoDB 重新连接成功');
      this.reconnectAttempts = 0;
    });

    // 进程退出时关闭连接
    process.on('SIGINT', async () => {
      await this.disconnect();
      process.exit(0);
    });

    process.on('SIGTERM', async () => {
      await this.disconnect();
      process.exit(0);
    });
  }

  /**
   * 处理重连逻辑
   */
  private async handleReconnection(): Promise<void> {
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      logger.error(`MongoDB 重连失败，已达到最大重试次数: ${this.maxReconnectAttempts}`);
      process.exit(1);
    }

    this.reconnectAttempts++;
    logger.info(`尝试重连 MongoDB (${this.reconnectAttempts}/${this.maxReconnectAttempts})...`);

    setTimeout(async () => {
      try {
        await mongoose.connect(config.MONGODB_URI);
        logger.info('MongoDB 重连成功');
        this.reconnectAttempts = 0;
      } catch (error) {
        logger.error(`MongoDB 重连失败 (第${this.reconnectAttempts}次):`, error);
        await this.handleReconnection();
      }
    }, this.reconnectInterval);
  }

  /**
   * 断开数据库连接
   */
  async disconnect(): Promise<void> {
    try {
      await mongoose.connection.close();
      logger.info('MongoDB 连接已关闭');
    } catch (error) {
      logger.error('关闭 MongoDB 连接时出错:', error);
    }
  }

  /**
   * 获取连接状态
   */
  getConnectionStatus(): {
    isConnected: boolean;
    readyState: number;
    readyStateText: string;
    host?: string;
    port?: number;
    name?: string;
  } {
    const readyStates = {
      0: 'disconnected',
      1: 'connected',
      2: 'connecting',
      3: 'disconnecting',
    };

    const connection = mongoose.connection;
    return {
      isConnected: connection.readyState === 1,
      readyState: connection.readyState,
      readyStateText: readyStates[connection.readyState as keyof typeof readyStates] || 'unknown',
      host: connection.host,
      port: connection.port,
      name: connection.name,
    };
  }

  /**
   * 健康检查
   */
  async healthCheck(): Promise<boolean> {
    try {
      if (mongoose.connection.readyState !== 1) {
        return false;
      }
      await mongoose.connection.db?.admin().ping();
      return true;
    } catch (error) {
      logger.error('数据库健康检查失败:', error);
      return false;
    }
  }
}

export const dbMonitor = new DatabaseMonitor();
export default dbMonitor;